package com.kevin.controller.controller.system;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fhs.core.trans.anno.TransMethodResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kevin.common.api.PageDTO;
import com.kevin.common.api.R;
import com.kevin.common.storage.StorageService;
import com.kevin.service.config.StpUserHolder;
import com.kevin.service.dto.UserExcelUpdateDTO;
import com.kevin.service.entity.SysUser;
import com.kevin.service.query.SysUserQuery;
import com.kevin.service.service.SysUserRoleService;
import com.kevin.service.service.SysUserService;
import com.kevin.service.vo.SysUserPasswordVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 系统用户控制器
 *
 * @author wh
 * @date 2023/03/27
 */
@RestController
@RequestMapping("sys/user")
@AllArgsConstructor
@Api(tags = "用户管理")
public class SysUserController {
    private final SysUserService userService;
    private final PasswordEncoder passwordEncoder;
    private final SysUserRoleService userRoleService;
    private final StorageService storageService;

    @GetMapping("page")
    @ApiOperation(value = "分页")
    @TransMethodResult
    public R<?> page(PageDTO pageDTO, SysUserQuery query) {
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
        return R.ok(new PageInfo<>(listByQuery(query)));
    }

    private List<SysUser> listByQuery(SysUserQuery query) {
        List<SysUser> list = userService.list(Wrappers.lambdaQuery(SysUser.class)
                .like(StrUtil.isNotBlank(query.getUsername()), SysUser::getUsername, query.getUsername())
                .like(StrUtil.isNotBlank(query.getMobile()), SysUser::getMobile, query.getMobile())
                .eq(query.getOrgId() != null, SysUser::getOrgId, query.getOrgId())
                .apply(CollUtil.isNotEmpty(query.getMajorIdList()), String.format("JSON_OVERLAPS( major_id_list,JSON_ARRAY(%s))", CollUtil.join(query.getMajorIdList(), ",")))
                .eq(query.getGender() != null, SysUser::getGender, query.getGender())
                .like(StrUtil.isNotBlank(query.getRealName()), SysUser::getRealName, query.getRealName())

        );
        return list;
    }

    @GetMapping(value = "export")
    @ApiOperation(value = "用户数据导出")
    public void userUpdateExport(SysUserQuery query, HttpServletResponse response) throws IOException {
        List<UserExcelUpdateDTO> list = listByQuery(query).stream().map(e -> {
            UserExcelUpdateDTO dto = BeanUtil.toBean(e, UserExcelUpdateDTO.class);
            dto.setId(String.valueOf(e.getId()));
            return dto;
        }).collect(Collectors.toList());

        // 告诉浏览器用什么软件可以打开此文件
        response.setHeader("content-Type", "application/vnd.ms-excel");
        // 下载文件的默认名称
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("用户数据导出.xlsx", "utf-8"));
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");

        EasyExcel.write(response.getOutputStream(), UserExcelUpdateDTO.class)
                .sheet("Sheet1")
                .doWrite(list);
    }

    @GetMapping("list")
    @ApiOperation(value = "列表")
    public R<?> list(SysUserQuery query) {
        return R.ok(listByQuery(query));
    }

    @GetMapping("{id}")
    @ApiOperation(value = "信息")
    @SaCheckPermission(value = "sys:user:info")
    public R<SysUser> get(@PathVariable("id") Long id) {
        SysUser entity = userService.getById(id);
        Assert.notNull(entity, "用户不存在!");
        // 用户角色列表
        List<Long> roleIdList = userRoleService.getRoleIdList(id);
        entity.setRoleIdList(roleIdList);
        entity.setPassword(null);
        return R.ok(entity);
    }


    @PutMapping("password")
    @ApiOperation(value = "修改密码")
    public R<String> password(@RequestBody @Valid SysUserPasswordVO vo) {
        // 原密码不正确
        SysUser user = StpUserHolder.getUserFromSession();
        if (!passwordEncoder.matches(vo.getPassword(), user.getPassword())) {
            return R.failed("原密码不正确");
        }
        if (Objects.equals(vo.getPassword(), vo.getNewPassword())) {
            return R.failed("新密码不能与旧密码相同!");
        }

        // 修改密码
        userService.updatePassword(user.getId(), passwordEncoder.encode(vo.getNewPassword()));
        return R.ok();
    }

    @PostMapping
    @ApiOperation(value = "保存")
    @SaCheckPermission(value = "sys:user:save")
    public R<String> save(@RequestBody @Valid SysUser vo) {
        // 保存
        userService.saveP(vo);

        return R.ok();
    }

    @PutMapping
    @ApiOperation(value = "修改")
    @SaCheckPermission(value = "sys:user:update")
    public R<String> update(@RequestBody @Valid SysUser vo) {
        if (StrUtil.isBlank(vo.getPassword())) {
            vo.setPassword(null);
        } else {
            vo.setPassword(passwordEncoder.encode(vo.getPassword()));
        }
        userService.update(vo);

        return R.ok();
    }

    @DeleteMapping
    @ApiOperation(value = "删除")
    @SaCheckPermission(value = "sys:user:delete")
    public R<String> delete(@RequestBody List<Long> idList) {
        Long userId = StpUserHolder.getId();
        if (idList.contains(userId)) {
            return R.failed("不能删除当前登录用户");
        }
        userService.delete(idList);
        return R.ok();
    }
}
